import { useQuery } from '@tanstack/vue-query'
import { computed, toRef, watchEffect, type Ref } from 'vue'
import { useRoute } from 'vue-router'

import {
  ApiSearchReport,
  subscribeReport,
  useGetReport,
  useGetReportQueryKey,
  useSearchReportQueryKey
} from '@/apis/report'
import { LabID } from '@/constants/lab'
import { useUserStore } from '@/stores/user'
import type { MimoContent } from '@/apis/lab'
import { Message } from '@arco-design/web-vue'
import { queryClient } from '@/apis/client'

const enum MimoLabStatus {
  Decoding = 1 << 6,
  Plotting = 1 << 7
}

export function useCurrentReportID() {
  const user = toRef(useUserStore(), 'user')
  const route = useRoute()

  const { data: reports } = useQuery({
    staleTime: 60_000,
    queryKey: useSearchReportQueryKey(
      computed(() => ({
        classID: +route.params.classID,
        student: user.value.username,
        experimentID: LabID.MIMOSimulator
      }))
    ),
    queryFn: ({ queryKey: [, , query] }) => ApiSearchReport(query),
    select({ data }) {
      return data?.[0]
    }
  })

  const reportID = computed<number>(() => reports.value?.id ?? 0)
  return {
    reportID
  }
}

export function useCurrentReport(reportID: Ref<number>) {
  const { data: report } = useGetReport<MimoContent>(
    reportID,
    computed(() => reportID.value > 0)
  )

  const isDecoding = computed(() => ((report.value?.status ?? 0) & MimoLabStatus.Decoding) !== 0)
  const isPlotting = computed(() => ((report.value?.status ?? 0) & MimoLabStatus.Plotting) !== 0)
  const subscribe = (id: number) => {
    const abortController = subscribeReport(id, {
      async onopen(res) {
        if (res.status === 200) {
          Message.success('已订阅该实验')
        }
      },
      onmessage(ev) {
        if (ev.event === 'message') {
          Message.success('已更新订阅')
          queryClient.invalidateQueries({ queryKey: useGetReportQueryKey(id) })
        }
      },
      onerror(err) {
        Message.error(err.message)
      },
      onclose() {
        Message.success('已结束该订阅')
      }
    })

    return abortController
  }

  watchEffect((onClean) => {
    const status = report.value?.status ?? 0
    const isRunning = (status & (MimoLabStatus.Decoding | MimoLabStatus.Plotting)) !== 0

    if (isRunning) {
      const abortController = subscribe(reportID.value)
      onClean(() => !abortController.signal.aborted && abortController.abort())
    }
  })
  return {
    isDecoding,
    isPlotting,

    report
  }
}
